package com.demo.controller;

import com.demo.dao.VenueDao;
import com.demo.entity.Venue;
import com.demo.service.VenueService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.transaction.annotation.Transactional;

import java.util.stream.IntStream;

import static org.hamcrest.Matchers.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("test")
@Transactional
public class VenueControllerIT {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private VenueService venueService;

    @Autowired
    private VenueDao venueDao;

    private static final int TOTAL_VENUES = 12;

    @BeforeEach
    void setup() {
        // 清空并初始化测试数据
        venueDao.deleteAll();

        // 生成 12 个场地数据
        IntStream.rangeClosed(1, TOTAL_VENUES).forEach(i -> {
            Venue venue = new Venue(
                    i,  // venueID
                    "Venue" + i,
                    "场地描述" + i,
                    100 + i,  // 价格
                    "venue" + i + ".jpg",  // 图片路径
                    "地址" + i,
                    "08:00",  // 开放时间
                    "22:00"   // 关闭时间
            );
            venueDao.save(venue);
        });

        // 验证数据插入
        assertAll(
                () -> assertEquals(TOTAL_VENUES, venueDao.count(), "总场地数量不匹配")
        );
    }

    @Test
    void getVenueDetail_ShouldReturnVenuePage_WhenValidId() throws Exception {
        // 获取第一个场馆
        int venueId = venueService.findAll().get(0).getVenueID();
        Venue firstVenue = venueService.findByVenueID(venueId);

        mockMvc.perform(get("/venue").param("venueID", String.valueOf(venueId)))
                .andExpect(status().isOk())
                .andExpect(view().name("venue"))
                .andExpect(model().attributeExists("venue"))
                .andExpect(model().attribute("venue", firstVenue));
    }

    @Test
    void getVenueList_ShouldReturnFirstPage() throws Exception {
        mockMvc.perform(get("/venuelist/getVenueList"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.content", hasSize(5))) // 默认每页5条
                .andExpect(jsonPath("$.content[0].venueName").value("Venue1"))
                .andExpect(jsonPath("$.totalPages", is(3))) // 12/5=3页
                .andExpect(jsonPath("$.totalElements", is(TOTAL_VENUES)));
    }

    @Test
    void getVenueList_ShouldReturnSecondPage() throws Exception {
        mockMvc.perform(get("/venuelist/getVenueList").param("page", "2"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.content", hasSize(5)))
                .andExpect(jsonPath("$.content[0].venueName").value("Venue6")); // 第二页第一条
    }

    @Test
    void getVenueList_ShouldReturnLastPage() throws Exception {
        mockMvc.perform(get("/venuelist/getVenueList").param("page", "3"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.content", hasSize(2))) // 第三页剩余2条
                .andExpect(jsonPath("$.content[0].venueName", is("Venue11")));
    }

    @Test
    void venueListPage_ShouldShowFirstPageData() throws Exception {
        mockMvc.perform(get("/venue_list"))
                .andExpect(status().isOk())
                .andExpect(view().name("venue_list"))
                .andExpect(model().attributeExists("venue_list"))
                .andExpect(model().attribute("total", 3)) // 总页数
                .andExpect(model().attribute("venue_list", hasSize(5)));
    }

    //================= 边界情况测试 =================//
    @Test
    void shouldHandlePageOutOfRangeGracefully() throws Exception {
        // 请求超过总页数的页码
        mockMvc.perform(get("/venuelist/getVenueList").param("page", "10"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.content", hasSize(0)));
    }

}
